package com.myKng.search.service.impl;

import com.myKng.search.model.KnowledgeDocument;
import com.myKng.search.repository.es.KnowledgeDocumentRepository;
import com.myKng.search.service.SearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 搜索服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SearchServiceImpl implements SearchService {

    private final KnowledgeDocumentRepository documentRepository;
    private final ElasticsearchOperations elasticsearchOperations;

    @Override
    public Page<KnowledgeDocument> searchByKeyword(String keyword, Pageable pageable) {
        log.debug("根据关键词搜索: {}", keyword);
        
        if (!StringUtils.hasText(keyword)) {
            return Page.empty(pageable);
        }
        
        // 构建查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("title", keyword).boost(3.0f))
                .should(QueryBuilders.matchQuery("fileName", keyword).boost(2.0f))
                .should(QueryBuilders.matchQuery("content", keyword).boost(1.0f))
                .should(QueryBuilders.matchQuery("description", keyword).boost(1.5f));
        
        // 创建搜索查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withPageable(pageable)
                .build();
        
        // 执行搜索
        SearchHits<KnowledgeDocument> searchHits = elasticsearchOperations.search(searchQuery, KnowledgeDocument.class);
        
        // 转换结果
        List<KnowledgeDocument> documents = searchHits.getSearchHits().stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());
        
        return new PageImpl<>(documents, pageable, searchHits.getTotalHits());
    }

    @Override
    public Page<KnowledgeDocument> advancedSearch(Map<String, Object> params, Pageable pageable) {
        log.debug("执行高级搜索，参数: {}", params);
        
        // 构建查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        
        // 处理关键词搜索
        if (params.containsKey("keyword") && StringUtils.hasText((String) params.get("keyword"))) {
            String keyword = (String) params.get("keyword");
            queryBuilder.must(QueryBuilders.multiMatchQuery(keyword, "title", "content", "fileName", "description"));
        }
        
        // 处理文件类型
        if (params.containsKey("fileType") && StringUtils.hasText((String) params.get("fileType"))) {
            String fileType = (String) params.get("fileType");
            queryBuilder.must(QueryBuilders.termQuery("fileType", fileType));
        }
        
        // 处理标签
        if (params.containsKey("tag") && StringUtils.hasText((String) params.get("tag"))) {
            String tag = (String) params.get("tag");
            queryBuilder.must(QueryBuilders.termQuery("tags", tag));
        }
        
        // 处理创建者
        if (params.containsKey("creatorId") && StringUtils.hasText((String) params.get("creatorId"))) {
            String creatorId = (String) params.get("creatorId");
            queryBuilder.must(QueryBuilders.termQuery("creatorId", creatorId));
        }
        
        // 处理时间范围
        if (params.containsKey("startTime") && params.containsKey("endTime")) {
            Long startTime = Long.valueOf(params.get("startTime").toString());
            Long endTime = Long.valueOf(params.get("endTime").toString());
            queryBuilder.must(QueryBuilders.rangeQuery("createTime").from(startTime).to(endTime));
        }
        
        // 创建搜索查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withPageable(pageable)
                .build();
        
        // 执行搜索
        SearchHits<KnowledgeDocument> searchHits = elasticsearchOperations.search(searchQuery, KnowledgeDocument.class);
        
        // 转换结果
        List<KnowledgeDocument> documents = searchHits.getSearchHits().stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());
        
        return new PageImpl<>(documents, pageable, searchHits.getTotalHits());
    }

    @Override
    public Page<KnowledgeDocument> searchByFileType(String fileType, Pageable pageable) {
        log.debug("按文件类型搜索: {}", fileType);
        return documentRepository.findByFileType(fileType, pageable);
    }

    @Override
    public Page<KnowledgeDocument> searchByTag(String tag, Pageable pageable) {
        log.debug("按标签搜索: {}", tag);
        return documentRepository.findByTagsContaining(tag, pageable);
    }

    @Override
    public List<String> getSuggestions(String prefix, int limit) {
        log.debug("获取搜索建议，前缀: {}, 限制: {}", prefix, limit);
        
        if (!StringUtils.hasText(prefix)) {
            return new ArrayList<>();
        }
        
        // 构建查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .should(QueryBuilders.prefixQuery("title.keyword", prefix).boost(2.0f))
                .should(QueryBuilders.prefixQuery("fileName.keyword", prefix));
        
        // 创建搜索查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withMaxResults(limit)
                .build();
        
        // 执行搜索
        SearchHits<KnowledgeDocument> searchHits = elasticsearchOperations.search(searchQuery, KnowledgeDocument.class);
        
        // 提取建议
        return searchHits.getSearchHits().stream()
                .map(hit -> hit.getContent().getTitle())
                .distinct()
                .limit(limit)
                .collect(Collectors.toList());
    }

    @Override
    public List<KnowledgeDocument> getRelatedDocuments(String documentId, int limit) {
        log.debug("获取相关推荐，文档ID: {}, 限制: {}", documentId, limit);
        
        // 获取当前文档
        KnowledgeDocument document = documentRepository.findById(documentId).orElse(null);
        if (document == null) {
            return new ArrayList<>();
        }
        
        // 构建查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("title", document.getTitle()).boost(2.0f))
                .should(QueryBuilders.matchQuery("content", document.getContent()).boost(1.0f))
                .mustNot(QueryBuilders.termQuery("id", documentId)); // 排除当前文档
        
        // 如果有标签，添加标签匹配
        if (document.getTags() != null && !document.getTags().isEmpty()) {
            queryBuilder.should(QueryBuilders.termsQuery("tags", document.getTags()).boost(3.0f));
        }
        
        // 创建搜索查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withMaxResults(limit)
                .build();
        
        // 执行搜索
        SearchHits<KnowledgeDocument> searchHits = elasticsearchOperations.search(searchQuery, KnowledgeDocument.class);
        
        // 转换结果
        return searchHits.getSearchHits().stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());
    }

    @Override
    public KnowledgeDocument indexDocument(KnowledgeDocument document) {
        log.debug("索引文档: {}", document.getFileName());
        return documentRepository.save(document);
    }

    @Override
    public List<KnowledgeDocument> indexDocuments(List<KnowledgeDocument> documents) {
        log.debug("批量索引文档，数量: {}", documents.size());
        List<KnowledgeDocument> savedDocuments = new ArrayList<>();
        documentRepository.saveAll(documents).forEach(savedDocuments::add);
        return savedDocuments;
    }

    @Override
    public void deleteDocument(String documentId) {
        log.debug("删除文档索引，ID: {}", documentId);
        documentRepository.deleteById(documentId);
    }

    @Override
    public KnowledgeDocument updateDocument(KnowledgeDocument document) {
        log.debug("更新文档索引: {}", document.getFileName());
        return documentRepository.save(document);
    }
}